package com.jeeplus.modules.act.listener;

import com.jeeplus.common.utils.StringUtils;
import org.activiti.engine.*;
import org.activiti.engine.delegate.DelegateTask;
import org.activiti.engine.delegate.Expression;
import org.activiti.engine.delegate.TaskListener;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.bpmn.behavior.ParallelMultiInstanceBehavior;
import org.activiti.engine.impl.bpmn.behavior.UserTaskActivityBehavior;
import org.activiti.engine.impl.javax.el.ExpressionFactory;
import org.activiti.engine.impl.javax.el.ValueExpression;
import org.activiti.engine.impl.juel.ExpressionFactoryImpl;
import org.activiti.engine.impl.juel.SimpleContext;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmActivity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.task.TaskDefinition;
import org.activiti.engine.task.Task;

import java.util.*;

public class CompeteListener implements TaskListener {
    private ProcessEngine processEngine = ProcessEngines.getDefaultProcessEngine();

    TaskService taskService = ProcessEngines.getDefaultProcessEngine().getTaskService() ;

    RuntimeService runtimeService = ProcessEngines.getDefaultProcessEngine().getRuntimeService();

    RepositoryService repositoryService = ProcessEngines.getDefaultProcessEngine().getRepositoryService();

    Map<String, Object> map = null;

    /**

     * @Fields serialVersionUID : TODO(用一句话描述这个变量表示什么)

     */

    private static final long serialVersionUID = -267105696009597215L;

    @Override

    public void notify(DelegateTask arg0) {

        try {

            arg0.setVariable("partyList", new ArrayList<String>());

            List<String> userList = new ArrayList<String>();

            map = arg0.getVariables();

            TaskDefinition taskDefinition = getNextTaskInfo(arg0.getProcessInstanceId());

            if(taskDefinition != null){

                Set<Expression> roleId = taskDefinition.getCandidateGroupIdExpressions();

                System.out.println("下个节点名称:"+taskDefinition.getNameExpression()+"========================");

                System.out.println("下个节点审批角色:"+taskDefinition.getCandidateGroupIdExpressions()+"===========================");

            }

        } catch (Exception e) {

            // TODO Auto-generated catch block

            e.printStackTrace();

        }

    }



    /**

     * 获取下一个userTask任务信息

     * @param processInstanceId   流程实例Id

     * @return  下一个用户任务定义信息

     * @throws Exception

     */

    public TaskDefinition getNextTaskInfo(String processInstanceId) throws Exception {
        ProcessDefinitionEntity processDefinitionEntity = null;
        String id = null;
        TaskDefinition task = null;
        //获取流程发布Id信息
        String definitionId = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult().getProcessDefinitionId();
        processDefinitionEntity = (ProcessDefinitionEntity) ((RepositoryServiceImpl) repositoryService)
                .getDeployedProcessDefinition(definitionId);
        List<Task> taskQuery = processEngine.getTaskService().createTaskQuery().processInstanceId(processInstanceId).list();
        //当前流程节点Id信息
        String activitiId = taskQuery.get(0).getTaskDefinitionKey();
        //获取流程所有节点信息
        List<ActivityImpl> activitiList = processDefinitionEntity.getActivities();
        //遍历所有节点信息
        for(ActivityImpl activityImpl : activitiList){
            id = activityImpl.getId();
            if (activitiId.equals(id)) {
                //获取下一个节点信息
                task = nextTaskDefinition(activityImpl, activityImpl.getId(), processInstanceId);
                break;
            }
        }
        return task;
    }
    /**
     * 下一个任务节点信息,
     * 如果下一个节点为用户任务则直接返回,
     * 如果下一个节点为排他网关, 根据当前的流程变量及排他网关各分支配置的el表达式，判断走哪个分支及下个用户任务
     * 根据变量值分别执行排他网关后线路中的el表达式, 并找到el表达式通过的线路后的用户任务
     * @param activityImpl     流程节点信息
     * @param activityId             当前流程节点Id信息
     * @param processInstanceId      流程实例Id信息
     * @return  下一个用户节点任务信息
     */

    private TaskDefinition nextTaskDefinition(ActivityImpl activityImpl, String activityId, String processInstanceId){
        PvmActivity ac = null;
        Object s = null;
        // 如果遍历节点为用户任务并且节点不是当前节点信息
        if ("userTask".equals(activityImpl.getProperty("type")) && !activityId.equals(activityImpl.getId())) {
            // 获取该节点下一个节点信息
            if(((ActivityImpl) activityImpl).getActivityBehavior() instanceof UserTaskActivityBehavior){
                UserTaskActivityBehavior aaBehavior =  (UserTaskActivityBehavior)((ActivityImpl) activityImpl).getActivityBehavior();
                return ((UserTaskActivityBehavior)aaBehavior).getTaskDefinition();
            } else if(((ActivityImpl) activityImpl).getActivityBehavior() instanceof ParallelMultiInstanceBehavior){
                ParallelMultiInstanceBehavior aaBehavior =  (ParallelMultiInstanceBehavior)((ActivityImpl) activityImpl).getActivityBehavior();
                return ((UserTaskActivityBehavior)aaBehavior.getInnerActivityBehavior()).getTaskDefinition();
            }
        } else if("exclusiveGateway".equals(activityImpl.getProperty("type"))){// 当前节点为exclusiveGateway
            List<PvmTransition> outTransitions = activityImpl.getOutgoingTransitions();
            // 如果排他网关只有一条线路信息
            if (outTransitions.size() == 1) {
                return nextTaskDefinition((ActivityImpl) outTransitions.get(0).getDestination(), activityId,
                        processInstanceId);
            } else if (outTransitions.size() > 1) { // 如果排他网关有多条线路信息
                for (PvmTransition tr1 : outTransitions) {
                    s = tr1.getProperty("conditionText"); // 获取排他网关线路判断条件信息
                    // 判断el表达式是否成立
                    if (isCondition(activityImpl.getId(), StringUtils.trim(s.toString()))) {
                        return nextTaskDefinition((ActivityImpl) tr1.getDestination(), activityId,
                                processInstanceId);
                    }
                }
            }
        }else {
            // 获取节点所有流向线路信息
            List<PvmTransition> outTransitions = activityImpl.getOutgoingTransitions();
            List<PvmTransition> outTransitionsTemp = null;
            for (PvmTransition tr : outTransitions) {
                ac = tr.getDestination(); // 获取线路的终点节点
                // 如果流向线路为排他网关
                if ("exclusiveGateway".equals(ac.getProperty("type"))) {
                    outTransitionsTemp = ac.getOutgoingTransitions();
                    // 如果排他网关只有一条线路信息
                    if (outTransitionsTemp.size() == 1) {
                        return nextTaskDefinition((ActivityImpl) outTransitionsTemp.get(0).getDestination(), activityId,
                                processInstanceId);
                    } else if (outTransitionsTemp.size() > 1) { // 如果排他网关有多条线路信息
                        for (PvmTransition tr1 : outTransitionsTemp) {
                            s = tr1.getProperty("conditionText"); // 获取排他网关线路判断条件信息
                            // 判断el表达式是否成立
                            if (isCondition(ac.getId(), StringUtils.trim(s.toString()))) {
                                return nextTaskDefinition((ActivityImpl) tr1.getDestination(), activityId,
                                        processInstanceId);
                            }
                        }
                    }
                } else if ("userTask".equals(ac.getProperty("type"))) {
                    if(((ActivityImpl) ac).getActivityBehavior() instanceof UserTaskActivityBehavior){
                        UserTaskActivityBehavior aaBehavior =  (UserTaskActivityBehavior)((ActivityImpl) ac).getActivityBehavior();
                        return ((UserTaskActivityBehavior)aaBehavior).getTaskDefinition();
                    } else if(((ActivityImpl) ac).getActivityBehavior() instanceof ParallelMultiInstanceBehavior){
                        ParallelMultiInstanceBehavior aaBehavior =  (ParallelMultiInstanceBehavior)((ActivityImpl) ac).getActivityBehavior();
                        return ((UserTaskActivityBehavior)aaBehavior.getInnerActivityBehavior()).getTaskDefinition();
                    }
                } else {

                }
            }
            return null;
        }
        return null;
    }

    /**

     * 根据key和value判断el表达式是否通过信息
     * @param key    el表达式key信息
     * @param  el     el表达式信息
     * @return
     */
    public boolean isCondition(String key, String el) {
        ExpressionFactory factory = new ExpressionFactoryImpl();
        SimpleContext context = new SimpleContext();
        for (Map.Entry<String, Object> entry : map.entrySet()) {
            context.setVariable(entry.getKey(), factory.createValueExpression(entry.getValue(), getValueClass(entry.getValue())));
        }
        ValueExpression e = factory.createValueExpression(context, el, boolean.class);
        return (Boolean) e.getValue(context);
    }

    /**
     * @Title: getValueClass
     * @Description: TODO(根据值获取值类型)
     * @param obj
     * @return
     * @return Class<?> (这里用一句话描述返回结果说明)
     */

    public Class<?> getValueClass(Object obj){
        if (obj instanceof Boolean) {
            return Boolean.class;
        } else if(obj instanceof Integer){
            return Integer.class;
        } else if(obj instanceof String){
            return String.class;
        } else if(obj instanceof Long){
            return Long.class;
        } else if(obj instanceof Map){
            return Map.class;
        } else if(obj instanceof Collection){
            return Collection.class;
        } else if(obj instanceof java.util.List){
            return java.util.List.class;
        }else {
            return String.class;
        }
    }
}
